import React from 'react';
import {
    AtomicBlockUtils,
    Editor,
    EditorState,
    Entity,
    RichUtils,
    convertFromRaw,
    convertToRaw,
  } from 'draft-js';
import axios from 'axios';
import util from 'util';
import { connect } from 'react-redux'
import { saveGamePostEditor } from './actions';
import '../../static/css/Draft.css';
import './RichEditor.css'


class GamePostEditor extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      editorState: EditorState.createEmpty(),
    };

    this.focus = () => this.refs.editor.focus();
    this.onChange = (editorState) => this.setState({editorState});
    this.logState = () => {
      const content = this.state.editorState.getCurrentContent();
      console.log(convertToRaw(content));
    };

    this.handleKeyCommand = this._handleKeyCommand.bind(this);
    this.addMedia = this._addMedia.bind(this);
    this.addAudio = this._addAudio.bind(this);
    this.addImage = this._addImage.bind(this);
    this.addVideo = this._addVideo.bind(this);

    this.toggleBlockType = (type) => this._toggleBlockType(type);
    this.toggleInlineStyle = (style) => this._toggleInlineStyle(style);

    // Handle Uploading Image Logic
    this.handleUploadSubmit = this._handleUploadSubmit.bind(this);
    this.addUploadImage = this._addUploadImage.bind(this);
    this.addUpload_to_Editor = this._addUpload_to_Editor.bind(this);

    this.handleSaveGamePost = this._handleSaveGamePost.bind(this);
  }

  _handleSaveGamePost(e){
    e.preventDefault();
    const content = this.state.editorState.getCurrentContent();
    const draftjsRawObject = convertToRaw(content);
    console.log(draftjsRawObject);
    const postTitle = this.refs.title.value;
    console.log(postTitle);
    console.log({postTitle, draftjsRawObject});
    this.props.onSaveGamePostEditor(e, {postTitle, draftjsRawObject});

  }  

  _handleKeyCommand(command) {
    const {editorState} = this.state;
    const newState = RichUtils.handleKeyCommand(editorState, command);
    if (newState) {
      this.onChange(newState);
      return true;
    }
    return false;
  }

  // Rich Text Part
  _toggleBlockType(blockType) {
    this.onChange(
      RichUtils.toggleBlockType(
        this.state.editorState,
        blockType
      )
    );
  }

  _toggleInlineStyle(inlineStyle) {
    this.onChange(
      RichUtils.toggleInlineStyle(
        this.state.editorState,
        inlineStyle
      )
    );
  }

  // Media Part
  _addMedia(type) {
    const src = window.prompt('Enter a URL');
    if (!src) {
      return;
    }

    const entityKey = Entity.create(type, 'IMMUTABLE', {src});

    return AtomicBlockUtils.insertAtomicBlock(
      this.state.editorState,
      entityKey,
      ' '
    );
  }

  // Handle Uploading Image Logic
  _addUpload_to_Editor(img_id) {
    const src = '/api/upload/' + img_id
    console.log('adding this image to the Editor: ' + src)

    const entityKey = Entity.create('image', 'IMMUTABLE', {src});

    return AtomicBlockUtils.insertAtomicBlock(
      this.state.editorState,
      entityKey,
      ' '
    );
  }  

  _addAudio() {
    this.onChange(this._addMedia('audio'));
  }

  _addImage() {
    this.onChange(this._addMedia('image'));
  }

  _addUploadImage(img_id) {
    this.onChange(this._addUpload_to_Editor(img_id));
  }

  _addVideo() {
    this.onChange(this._addMedia('video'));
  }


  // Handle Uploading Image Logic
  _handleUploadSubmit(e) {
    var self = this;
    e.preventDefault();
    // TODO: do something with -> this.state.file
    let file = this.refs.file_input.files[0]  
    // console.log(file)
    const data = new FormData()
    data.append('file', file)
    axios.post('/api/upload', data)
            .then(function (res) {
              console.log('upload success, image id:')
              console.log(util.inspect(res.data, false, null))
              self._addUploadImage(res.data)
            })
            .catch(function (err) {
              console.log('error' + err.message)
            })
  }

  render() {

    const {editorState} = this.state;
    // If the user changes block type before entering any text, we can
    // either style the placeholder or hide it. Let's just hide it now.
    let className = 'RichEditor-editor';
    var contentState = editorState.getCurrentContent();
    if (!contentState.hasText()) {
      if (contentState.getBlockMap().first().getType() !== 'unstyled') {
        className += ' RichEditor-hidePlaceholder';
      }
    }

    return (
      <div>
        <div className="form-group">
          <label for="title" className="col-lg-1 control-label">Title</label>
          <div className="col-lg-6">
            <input type="text" ref="title" placeholder="please add a title" className="form-control"/>
          </div>
        </div>

        <div className="RichEditor-root" style={styles.root}>

          <br/>

          <BlockStyleControls
            editorState={this.state.editorState}
            onToggle={this.toggleBlockType}
          />
          <InlineStyleControls
            editorState={this.state.editorState}
            onToggle={this.toggleInlineStyle}
          />

          <div style={{marginBottom: 10}}>
            Pls use the editor.
          </div>

          <div style={styles.buttons}>
            <button onMouseDown={this.addAudio} style={{marginRight: 10}}>
              Add Audio
            </button>
            <button onMouseDown={this.addVideo} style={{marginRight: 10}}>
              Add Video
            </button>
            <button onMouseDown={this.addImage} style={{marginRight: 10}}>
              Add Image
            </button>       

            <hr></hr>
            <form>
              <input type="file" ref="file_input" />
              <button type="submit" onClick={this.handleUploadSubmit}>Upload Image</button>
            </form>
            <hr></hr>
          </div>

          <div style={styles.editor} onClick={this.focus}>
            <Editor
              blockStyleFn={getBlockStyle}
              blockRendererFn={mediaBlockRenderer}
              customStyleMap={styleMap}
              editorState={this.state.editorState}
              handleKeyCommand={this.handleKeyCommand}
              onChange={this.onChange}
              placeholder="Enter some text..."
              ref="editor"
              spellCheck={true}
            />
          </div>

          <input
            onClick={this.logState}
            style={styles.button}
            type="button"
            value="Log State"
          />

          <input
            onClick={this.handleSaveGamePost}
            style={styles.button}
            type="button"
            value="Save Game Post"
          />
        </div>
      </div>  
    );
  }
}

// Custom overrides for "code" style.
const styleMap = {
  CODE: {
    backgroundColor: 'rgba(0, 0, 0, 0.05)',
    fontFamily: '"Inconsolata", "Menlo", "Consolas", monospace',
    fontSize: 16,
    padding: 2,
  },
};

function getBlockStyle(block) {
  switch (block.getType()) {
    case 'blockquote': return 'RichEditor-blockquote';
    default: return null;
  }
}

class StyleButton extends React.Component {
  constructor() {
    super();
    this.onToggle = (e) => {
      e.preventDefault();
      this.props.onToggle(this.props.style);
    };
  }

  render() {
    let className = 'RichEditor-styleButton';
    if (this.props.active) {
      className += ' RichEditor-activeButton';
    }

    return (
      <span className={className} onMouseDown={this.onToggle}>
        {this.props.label}
      </span>
    );
  }
}

const BLOCK_TYPES = [
  {label: 'H1', style: 'header-one'},
  {label: 'H2', style: 'header-two'},
  {label: 'H3', style: 'header-three'},
  {label: 'H4', style: 'header-four'},
  {label: 'H5', style: 'header-five'},
  {label: 'H6', style: 'header-six'},
  {label: 'Blockquote', style: 'blockquote'},
  {label: 'UL', style: 'unordered-list-item'},
  {label: 'OL', style: 'ordered-list-item'},
  {label: 'Code Block', style: 'code-block'},
];

const BlockStyleControls = (props) => {
  const {editorState} = props;
  const selection = editorState.getSelection();
  const blockType = editorState
    .getCurrentContent()
    .getBlockForKey(selection.getStartKey())
    .getType();

  return (
    <div className="RichEditor-controls">
      {BLOCK_TYPES.map((type) =>
        <StyleButton
          key={type.label}
          active={type.style === blockType}
          label={type.label}
          onToggle={props.onToggle}
          style={type.style}
        />
      )}
    </div>
  );
}


var INLINE_STYLES = [
  {label: 'Bold', style: 'BOLD'},
  {label: 'Italic', style: 'ITALIC'},
  {label: 'Underline', style: 'UNDERLINE'},
  {label: 'Monospace', style: 'CODE'},
];

const InlineStyleControls = (props) => {
  var currentStyle = props.editorState.getCurrentInlineStyle();
  return (
    <div className="RichEditor-controls">
      {INLINE_STYLES.map(type =>
        <StyleButton
          key={type.label}
          active={currentStyle.has(type.style)}
          label={type.label}
          onToggle={props.onToggle}
          style={type.style}
        />
      )}
    </div>
  );
}


// Media Part
function mediaBlockRenderer(block) {
  if (block.getType() === 'atomic') {
    return {
      component: Media,
      editable: false,
    };
  }

  return null;
}

const Audio = (props) => {
  return <audio controls src={props.src} style={styles.media} />;
};

const Image = (props) => {
  return <img src={props.src} style={styles.media} />;
};

const Video = (props) => {
  return <video controls src={props.src} style={styles.media} />;
};

const Media = (props) => {
  const entity = Entity.get(props.block.getEntityAt(0));
  const {src} = entity.getData();
  const type = entity.getType();

  let media;
  if (type === 'audio') {
    media = <Audio src={src} />;
  } else if (type === 'image') {
    media = <Image src={src} />;
  } else if (type === 'video') {
    media = <Video src={src} />;
  }

  return media;
};

const styles = {
  root: {
    fontFamily: '\'Georgia\', serif',
    padding: 20,
    width: 600,
  },
  buttons: {
    marginBottom: 10,
  },
  editor: {
    border: '1px solid #ccc',
    cursor: 'text',
    minHeight: 80,
    padding: 10,
  },
  button: {
    marginTop: 10,
    textAlign: 'center',
  },
  media: {
    width: '100%',
  },
};


function mapStateToProps(state, ownProps) {
  const {
    gamePostEditor: { saved, saving },
  } = state

  return {
    saved,
    saving
  }
}


function mapDispatchToProps(dispatch) {
  return {
    onSaveGamePostEditor: (e, payload) => 
    {e.preventDefault();dispatch(saveGamePostEditor(payload))},
    dispatch,
  };
}


module.exports = connect(mapStateToProps, mapDispatchToProps)(GamePostEditor)